package com.ferry.jraft.example;

import com.ferry.jraft.StateMachine;
import com.ferry.jraft.model.LogEntry;
import lombok.extern.slf4j.Slf4j;

import java.util.Stack;

/**
 * @Author ferry
 * @create 2022/5/25 22:12
 * @description 栈计算器的状态机
 */
@Slf4j
public class StackStateMachine implements StateMachine {

    private Stack<Integer> stack=new Stack<>();

    @Override
    public void init() throws Throwable {
        log.info("StateMachine init");
    }

    @Override
    public void destroy() throws Throwable {
        log.info("StateMachine destroy");
    }

    @Override
    public Object apply(LogEntry logEntry) {
        String val= logEntry.getValue();
        int index = val.indexOf(' ');
        String operation=val.substring(0,index);
        String number=val.substring(index+1);
        switch (operation){
            case "push":{
                stack.push(Integer.parseInt(number));
                return "ok";
            }
            case "pop":{
                if(stack.isEmpty()){
                    return "fail";
                }
                return stack.pop().toString();
            }
            case "add":{
                if(stack.size()<2){
                    return "fail";
                }
                int a1=stack.pop();
                int a2=stack.pop();
                stack.push(a1+a2);
                return "ok";
            }
            case "sub":{
                if(stack.size()<2){
                    return "fail";
                }
                int s1=stack.pop();
                int s2=stack.pop();
                stack.push(s1-s2);
                return "ok";
            }
            case "mul":{
                if(stack.size()<2){
                    return "fail";
                }
                int m1=stack.pop();
                int m2=stack.pop();
                stack.push(m1*m2);
                return "ok";
            }
            case "div":{
                if(stack.size()<2){
                    return "fail";
                }
                int d1=stack.pop();
                int d2=stack.pop();
                stack.push(d1/d2);
                return "ok";
            }
            case "inc":{
                if(stack.isEmpty()){
                    return "fail";
                }
                stack.push(stack.pop()+1);
                return "ok";
            }
            case "dec":{
                if(stack.isEmpty()){
                    return "fail";
                }
                stack.push(stack.pop()-1);
                return "ok";
            }
            case "get":{
                if(stack.isEmpty()){
                    return "fail";
                }
                return stack.peek().toString();
            }
            default:
                return "fail";
        }
    }
}
